import 'dart:convert';

class JsonEditor {
  static void test() {
    Object json = "{}";
    json = editJson(json, {
      "code": 0,
      "data!.users": [],
    });
    print("xxxx json = ${json}");
    json = editJson(json, {
      "data.users.[0]!.name": "哈哈哈哈",
      "data.users.[0].gender": 1,
      "data.users.[1]!": {"id": 0, "time": 1},
    });
    print("xxxx json = ${json}");

    json = "[]";
    json = editJson(json, {
      "code!": 0,
      "[0]": "hahahha",
      "[-1]!.name": "zzzzzz",
      "[0]!.gender!": 1
    });
    print("xxxx json = ${json}");
  }

  ///修改/添加/删除json中的部分内容
  ///tamperMap规则如下
  ///"errCode":10086  //根层级的errCode改为10086
  ///"data.users.[0].name":"测试一下特别长的名字的显示效果"  //修改users列表中第一个的name,如果users为空，则不会生效
  ///"data.users":[]  //data中的users置空
  ///"data.users!.[0]!":{"name":"111","gender":1,"avatar":"http://xxxx"}   //修改users列表中的第一个，如果user为null或[],则创建/插入
  static Object editJson(Object json, Map<dynamic, dynamic> tamperMap) {
    if (json is String) {
      json = jsonDecode(json);
    }
    if (json is Map || json is List) {
      //json是map或list结构
      tamperMap.forEach((key, value) {
        //逐项更改
        json = _jsonSingleEdit(json, key, value);
      });
      return json;
    }
    //不是map或list,返回本身
    return json;
  }

  static dynamic _jsonSingleEdit(
      dynamic jsonObj, String tamperPath, Object? tamperValue) {

    dynamic currentLevel = jsonObj;
    var stepList = tamperPath.split('.');
    var length = stepList.length;
    String finalStep = stepList.last;

    if (length > 1) {
      //不是在根层级直接修改，需要找到或者创建最终值的修改位置
      for (int i = 0; i < length - 1; i++) {
        String nextStep = stepList[i];
        String nextNextStep = stepList[i + 1];
        currentLevel =
            _getOrCreateNextLevel(currentLevel, nextStep, nextNextStep);
      }
    }

    if (currentLevel != null) {
      _modifyLastLevel(currentLevel, finalStep, tamperValue);
    }
    return jsonObj;
  }

  static void _modifyLastLevel(
      dynamic lastLevel, String lastStep, Object? tamperValue) {
    if (lastLevel is Map) {
      lastLevel[lastStep] = tamperValue;
    } else if (lastLevel is List) {
      //不存在是否创建
      bool forceCreate = false;
      if (lastStep.endsWith('!')) {
        //如果!结尾，则不存在时需要创建
        forceCreate = true;
        lastStep = lastStep.substring(0, lastStep.length - 1);
      }
      if (lastStep.startsWith('[') && lastStep.endsWith(']')) {
        var indexString = lastStep.substring(1, lastStep.length - 1);
        int? index = int.tryParse(indexString);
        if (index == null) {
          return;
        }
        if (index >= 0 && index < lastLevel.length) {
          //index在范围内
          if (tamperValue == null) {
            lastLevel.removeAt(index);
          } else {
            lastLevel[index] = tamperValue;
          }
        } else if (forceCreate && tamperValue != null) {
          //index不在范围内，直接添加
          lastLevel.add(tamperValue);
        }
      }
    }
  }

  ///取出名为[nextStep]下一个层级，当前找不到[nextStep]所代表的层级时，
  ///根据[nextNextStep]的传值确认[nextStep]的类型，必要时创建
  ///如
  ///[nextNextStep]为'[0]'时，说明[nextStep]需要为List类型，
  ///[nextNextStep]为其他字符串如'title'时，说明[nextStep]需要为Map类型
  static dynamic _getOrCreateNextLevel(
      dynamic currentLevel, String nextStep, String nextNextStep) {
    if (currentLevel == null) {
      return null;
    }
    //不存在是否创建
    bool forceCreate = false;
    if (nextStep.endsWith('!')) {
      //如果!结尾，则不存在时需要创建
      forceCreate = true;
      nextStep = nextStep.substring(0, nextStep.length - 1);
    }

    if (currentLevel is Map) {
      dynamic value = currentLevel[nextStep];
      if (value == null && forceCreate) {
        value = nextNextStep.startsWith('[') ? [] : {};
        currentLevel[nextStep] = value;
      }
      return value;
    } else if (currentLevel is List) {
      if (nextStep.startsWith('[') && nextStep.endsWith(']')) {
        var indexString = nextStep.substring(1, nextStep.length - 1);
        int? index = int.tryParse(indexString);
        if (index == null) {
          return null;
        }
        if (index >= 0 && index < currentLevel.length) {
          //index在范围内
          return currentLevel[index];
        } else if (forceCreate) {
          //index不在范围内，直接添加
          var value = nextNextStep.startsWith('[') ? [] : {};
          currentLevel.add(value);
          return value;
        }
      } else {
        return null;
      }
    } else {
      return null;
    }
  }
}
